// 头像接口类型
interface DataAvator {
  avator?: string
  time?: number | string
  name?: string
}

// 提问数据接口类型
interface Qs {
  questions: {
    title: string
    picture: string[]
  }
}

// 问题接口数据类型
interface As {
  answers: {
    text: string
    audio?: {
      url: string
      total: number
    }
  }
}
type Mixin<T, X> = T & X;

// 4. 实现Mixin 和  DataAvator
type MixWithDataAvator<T> = Mixin<DataAvator, T>;

// 组装Qs和As 拼接成想要的复杂数据类型
interface AskConfig {
  asker: MixWithDataAvator<Qs>
  answer?: MixWithDataAvator<As>
}

// 最终输出列表数组类型
type AskConfigList = AskConfig[];
const arrList: AskConfigList = [
  {
    asker: {
      name: '张三',
      avator: 'https://img.yzcdn.cn/vant/cat.jpeg',
      time: '2020-06-24',
      questions: {
        title: '你是谁',
        picture: [
          'https://img.yzcdn.cn/vant/cat.jpeg',
          'https://img.yzcdn.cn/vant/cat.jpeg',
          'https://img.yzcdn.cn/vant/cat.jpeg',
        ],
      }
    },
    answer: {
      name: '李四',
      avator: 'https://img.yzcdn.cn/vant/cat.jpeg',
      time: '2020-06-24',
      answers: {
        text: '我是李四',
        audio: {
          url: 'https://img.yzcdn.cn/vant/cat.jpeg',
          total: 10,
        }
      }
    },
  },
]


// 5. 实现UnPromisify下面代码保证不报错
async function personPromise() {
  return { name: "Semlinker", age: 30 } as Person0;
}

interface Person0 {
  name: string;
  age: number;
}

async function stringPromise() {
  return "Hello, Semlinker!";
}
console.log(typeof stringPromise);

type PromiseType<T> = (args: any[]) => Promise<T>;
type UnPromisify<T> = T extends PromiseType<infer U> ? U : never;

type extractStringPromise = UnPromisify<typeof stringPromise>; // string
type extractPersonPromise = UnPromisify<typeof personPromise>; // Person

// let a01 : extractStringPromise = 

type ReturnType1<T> = T extends Promise<infer R> ? R : any;
// res 必须是string
let res : ReturnType1<()=>string> =  '123'

// 反解promise的返回值
const promise1 = async ()=>`Promise.resolve(200)`
type PromiseType1 = ReturnType1<typeof promise1>
let p11 : PromiseType1 = `123`


// 7.修改代码 保证不报错
type User = {
  id: number;
  kind: string;
};

function makeCustomer<T extends User>(u: T): T {
  // Error（TS 编译器版本：v4.4.2）
  // Type '{ id: number; kind: string; }' is not assignable to type 'T'.
  // '{ id: number; kind: string; }' is assignable to the constraint of type 'T', 
  // but 'T' could be instantiated with a different subtype of constraint 'User'.
  return {
    id: u.id,
    kind: 'customer'
  }
}

// 8 . 本道题我们希望参数 `a` 和 `b` 的类型都是一致的，即 `a` 和 `b` 同时为 `number` 或 `string` 类型。当它们的类型不一致的值，TS 类型检查器能自动提示对应的错误信息。
function f(a: string | number, b: string | number) {
  if (typeof a === 'string') {
    return a + ':' + b; // no error but b can be number!
  } else {
    return a + b; // error as b can be number | string
  }
}

f(2, 3); // Ok
f(1, 'a'); // Error
f('a', 2); // Error
f('a', 'b') // Ok

// 9. 总结 : never void unknown any 类型的区别
// 10. 总结ts的关键字
// 11. 总结ts的type 和interface 区别而